package com.linzm.server;

import com.linzm.model.Request;
import com.linzm.model.Response;
import com.linzm.servlet.HttpServlet;
import lombok.SneakyThrows;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * v3 封装servlet
 *
 * @Date: 2023/11/6 21:37
 * @User linziming
 */
public class BootstrapV3 {
    private final static Map<String, HttpServlet> SERVLET_MAP = new HashMap<>();

    @SneakyThrows
    public static void main(String[] args) {
        ServerSocket serverSocket = new ServerSocket(8080);
        // 加载解析相关的配置 ，web.xml，把配置的servlet存入servletMap中
        BootstrapV3 bootstrapV3 = new BootstrapV3();
        bootstrapV3.loadServlet();
        /*
         * 可以请求动态资源
         */
        while (true) {
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            //封装Resuest对象和Response对象
            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());
            String url = request.getUrl();
            //静态资源处理
            if (SERVLET_MAP.get(url) == null) {
                response.outputHtml(request.getUrl());
            } else {
                //动态资源处理
                HttpServlet httpServlet = SERVLET_MAP.get(url);
                httpServlet.service(request, response);
            }
            socket.close();
        }
    }

    /**
     * 加载加息web.xml，初始化servlet
     */
    private void loadServlet() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            //根元素
            Element rootElement = document.getRootElement();
            /*
             * 1, 找到所有的servlet标签，找到servlet-name和servlet-class
             * 2, 根据servlet-name找到<servlet-mapping>中与其匹配的<url-pattern>
             */
            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element = selectNodes.get(i);
                /*
                 * 1, 找到所有的servlet标签，找到servlet-name和servlet-class
                 */
                //<servlet-name>dxh</servlet-name>
                Element servletNameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletNameElement.getStringValue();
                //<servlet-class>server.DxhServlet</servlet-class>
                Element servletClassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletClassElement.getStringValue();

                /*
                 * 2, 根据servlet-name找到<servlet-mapping>中与其匹配的<url-pattern>
                 */
                //Xpath表达式：从/web-app/servlet-mapping下查询，查询出servlet-name=servletName的元素
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']'");
                // /dxh
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                SERVLET_MAP.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
            }
        } catch (DocumentException | IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
